/**
 * 拖拽指令
 * option: {
 *     type: 'clone','move', // 拖拽类型
 *     value: '图片地址' // 组件内容
 *     fn: function // 拖动完触发的函数
 *     index: '' // 下标: type为move时有效
 * }
 * @type {{init: dragDirective.init, focus: (function(): {mounted(*): void}), drag: (function(): {beforeUnmount(*): void, unmounted(): void, beforeUpdate(): void, beforeMount(): void, mounted(*, *): void, updated(*)})}}
 */
const dragDirective = {
    init: (app) => {
        app.directive('drag', dragDirective.drag())
        app.directive('focus', dragDirective.focus())
    },
    drag: () => {
        return {
            // Directive has a set of lifecycle hooks:
            // called before bound element's parent component is mounted
            beforeMount() {
                console.log('beforeMount')
            },
            // called when bound element's parent component is mounted
            mounted(el, binding) {
                const option = {
                    type: binding.value.type || 'move',
                    value: binding.value.value || '',
                    fn: binding.value.fn || ''
                }
                option.type === 'move'
                    ? option.index = binding.value.index
                    : ''
                // 点击某物体时，用drag对象即可，move和up是全局区域，
                // 也就是整个文档通用，应该使用document对象而不是drag对象(否则，采用drag对象时物体只能往右方或下方移动)
                const drag = el
                drag.onmousedown = function(event) {
                    const eventDown = event || window.event // 兼容IE浏览器
                    const eventDownWidth = eventDown.target.offsetWidth
                    const eventDownHeight = eventDown.target.offsetHeight
                    const targetMoveDom = option.type === 'move'
                        ? drag
                        : document.getElementsByClassName('target-clone-class')
                    // 鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离
                    const diffX = eventDown.clientX - drag.offsetLeft
                    const diffY = eventDown.clientY - drag.offsetTop
                    if (typeof drag.setCapture !== 'undefined') {
                        drag.setCapture()
                    }
                    document.onmousemove = function(event) {
                        option.type === 'move' ? ''
                            : cloneVirtual(eventDown, targetMoveDom, eventDownWidth, eventDownHeight)
                        const eventMove = event || window.event
                        let moveX = eventMove.clientX - diffX
                        let moveY = eventMove.clientY - diffY
                        if (moveX < 0) {
                            moveX = 0
                        } else if (moveX > window.innerWidth - drag.offsetWidth) {
                            moveX = window.innerWidth - drag.offsetWidth
                        }
                        if (moveY < 0) {
                            moveY = 0
                        } else if (moveY > window.innerHeight - drag.offsetHeight) {
                            moveY = window.innerHeight - drag.offsetHeight
                        }
                        if (option.type === 'move') {
                            targetMoveDom.style.left = moveX + 'px'
                            targetMoveDom.style.top = moveY + 'px'
                        } else {
                            targetMoveDom[0].style.left = moveX + 'px'
                            targetMoveDom[0].style.top = moveY + 'px'
                        }
                    }
                    document.onmouseup = function(event) {
                        document.onmousemove = null
                        document.onmouseup = null
                        // 放置后渲染
                        if (targetMoveDom.length > 0) { // 防止重复添加多个虚影
                            for (let i = 0; i < targetMoveDom.length; i++) {
                                targetMoveDom[i].remove()
                            }
                        }
                        cloneRender(event, diffX, diffY)
                        if (typeof drag.releaseCapture !== 'undefined') {
                            drag.releaseCapture()
                        }
                    }
                }

                // 按下鼠标的拖拽效果
                const cloneVirtual = function(event, targetMoveDom, eventDownWidth, eventDownHeight) {
                    const targetClone = event.target.cloneNode(true) // 复制跟随鼠标移动的虚影
                    targetClone.classList.add('target-clone-class') // 添加虚影class
                    targetClone.style.width = eventDownWidth + 'px'
                    targetClone.style.height = eventDownHeight + 'px'
                    targetClone.style.zIndex = '1'
                    // targetClone.style.left = offsetLeft + 'px'
                    // targetClone.style.top = offsetTop + 'px'
                    if (targetMoveDom.length > 0) { // 防止重复添加多个虚影
                        for (let i = 0; i < targetMoveDom.length; i++) {
                            targetMoveDom[i].remove()
                        }
                    }
                    document.getElementsByTagName('body')[0].appendChild(targetClone) // 将虚影追加到body
                }

                // 放置元素效果
                const cloneRender = function(event, diffX, diffY) {
                    let param = {}
                    param = {
                        x: event.clientX - diffX,
                        y: event.clientY - diffY,
                        index: option.index,
                        value: option.value
                    }
                    option.fn(param)
                }
            },
            // called before the containing component's VNode is updated
            beforeUpdate() {
                console.log('beforeUpdate')
            },
            // called after the containing component's VNode and the VNodes of its children // have updated
            updated(e) {
            },
            // called before the bound element's parent component is unmounted
            beforeUnmount(e) {
                console.log('beforeUnmount')
            },
            // called when the bound element's parent component is unmounted
            unmounted() {
                console.log('unmounted')
            }
        }
    },
    focus: () => {
        return {
            mounted(el) {
                console.log('focus:::mounted')
                el.focus()
            }
        }
    }
}

export default dragDirective
